home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / libraries / dylan / extern.dylan < prev    next >
Encoding:
Text File  |  1995-03-15  |  8.7 KB  |  255 lines  |  [TEXT/ttxt]

  1. module: extern
  2. rcs-header: $Header: extern.dylan,v 1.1 94/11/06 20:11:59 rgs Locked $
  3.  
  4. //======================================================================
  5. //
  6. // Copyright (c) 1994  Carnegie Mellon University
  7. // All rights reserved.
  8. // 
  9. // Use and copying of this software and preparation of derivative
  10. // works based on this software are permitted, including commercial
  11. // use, provided that the following conditions are observed:
  12. // 
  13. // 1. This copyright notice must be retained in full on any copies
  14. //    and on appropriate parts of any derivative works.
  15. // 2. Documentation (paper or online) accompanying any system that
  16. //    incorporates this software, or any part of it, must acknowledge
  17. //    the contribution of the Gwydion Project at Carnegie Mellon
  18. //    University.
  19. // 
  20. // This software is made available "as is".  Neither the authors nor
  21. // Carnegie Mellon University make any warranty about the software,
  22. // its performance, or its conformity to any specification.
  23. // 
  24. // Bug reports, questions, comments, and suggestions should be sent by
  25. // E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  26. //
  27. //======================================================================
  28. //
  29. // This file contains definitions useful for calling native C functions from
  30. // within Mindy.  Many of these are intended to support the code produced by
  31. // Melange rather than being explicitly referenced by users.
  32. //
  33.  
  34. define constant gcf-unbound = pair(#f, #f); // hack
  35.  
  36. // This is potentially useful, but will probably be overshadowed by Melange.
  37. // It combines the functionality of "find-c-function" and
  38. // "constrain-c-function" to get usable function in one step.
  39. //
  40. define method get-c-function
  41.     (name :: <string>,
  42.      #key args, rest = ~args, result = <object>, file = gcf-unbound)
  43.  => (result :: <c-function>);
  44.   let real-args = if (args) as(<list>, args) else #() end if;
  45.   let real-result = if (instance?(result, <sequence>)) as(<list>, result)
  46.             else list(result)
  47.             end if;
  48.   let fun = if (file == gcf-unbound)
  49.           find-c-function(name)
  50.         else
  51.           find-c-function(name, file: file);
  52.         end if;
  53.   fun & constrain-c-function(fun, real-args, rest, real-result);
  54. end method get-c-function;
  55.  
  56. // These will be used by "make" and "destroy".
  57. //
  58. define constant malloc = get-c-function("malloc", args: list(<integer>),
  59.                     result: <statically-typed-pointer>);
  60. define constant c-free = get-c-function("free",
  61.                     args: list(<statically-typed-pointer>),
  62.                     result: #());
  63.  
  64. // Uses "free" to deallocate a native C pointer.
  65. //
  66. define generic destroy (ptr :: <statically-typed-pointer>) => ();
  67.  
  68. // Generic "dereference" operation.  Methods will be defined for individual
  69. // pointer types.
  70. //
  71. define open generic pointer-value
  72.     (ptr :: <statically-typed-pointer>, #key index);
  73. define open generic pointer-value-setter
  74.     (value :: <object>, ptr :: <statically-typed-pointer>, #key index);
  75.  
  76. // Generic function which will be extended with methods that describe the
  77. // sizes of particular pointer types.  If the size is unknown, it will return
  78. // 0.  "Structure-size" is defined as an alias for compatibility with Creole.
  79. //
  80. define open generic content-size
  81.     (cls :: limited(<class>, subclass-of: <statically-typed-pointer>))
  82.  => (result :: <integer>);
  83.  
  84. define constant structure-size = content-size;
  85.  
  86. // The import-value and export-value functions can be extended to add
  87. // user-defined type mapping to Melange.  Default methods are provided for
  88. // <statically-typed-pointer> and for <boolean>.
  89. //
  90. // Note that these functions are not compatible with the identically named
  91. // functions in Creole.
  92. //
  93. define open generic export-value
  94.     (low-level-class :: <class>, high-level-value :: <object>)
  95.  => (low-level-value :: <object>);
  96.  
  97. define open generic import-value
  98.     (high-level-class :: <class>, low-level-value :: <object>)
  99.  => (high-level-value :: <object>);
  100.  
  101. define method export-value
  102.     (low-level-class :: <class>, high-level-value :: <object>)
  103.  => (low-level-value :: <object>);
  104.   as(low-level-class, high-level-value);
  105. end method export-value;
  106.  
  107. define method import-value
  108.     (high-level-class :: <class>, low-level-value :: <object>)
  109.  => (high-level-value :: <object>);
  110.   as(high-level-class, low-level-value);
  111. end method import-value;
  112.  
  113. // Default make method for pointer values.  You may create a vector by
  114. // specifying "element-count:" and may adjust the size explicitly by
  115. // specifying "extra-bytes:".
  116. //
  117. define method make
  118.     (cls :: limited(<class>, subclass-of: <statically-typed-pointer>),
  119.      #key extra-bytes :: <integer> = 0,
  120.           pointer,
  121.           element-count :: <integer> = 1)
  122.  => (result :: <statically-typed-pointer>);
  123.   if (pointer)
  124.     select (pointer by instance?)
  125.       <statically-typed-pointer>,
  126.       <integer> =>
  127.     as(cls, pointer);
  128.       otherwise =>
  129.     error("Invalid pointer: keyword in make: %=", pointer);
  130.     end select;
  131.   else
  132.     if (element-count < 1)
  133.       error("Bad element-count: in make: %=", element-count);
  134.     end if;
  135.  
  136.     let ptr = malloc((content-size(cls) + extra-bytes) * size);
  137.     if (ptr == null-pointer) error("Make failed to allocate memory.") end if;
  138.  
  139.     as(cls, ptr);
  140.   end if;
  141. end method make;
  142.  
  143. // Explicitly destroys C pointers, since we cannot garbage collect them.
  144. //
  145. define method destroy (ptr :: <statically-typed-pointer>) => ();
  146.   c-free(ptr);
  147. end method destroy;
  148.  
  149. define class <machine-pointer> (<statically-typed-pointer>) end class;
  150.  
  151. // <C-string> corresponds to C's native "char *" type.  We provide basic
  152. // functions to that it obeys the protocol of <string>.
  153. //
  154. define class <c-string> (<statically-typed-pointer>, <string>) 
  155. end class <c-string>;
  156.  
  157. // We come up with an ambiguity in this special case, so define a method which
  158. // resolves it.
  159. // 
  160. define method as
  161.     (cls == <c-string>, value :: <c-string>) => (result :: <c-string>);
  162.   value;
  163. end method as;
  164.  
  165. // We might as well use the native c library routines when they do the right
  166. // thing anyway.
  167. //
  168. define constant strcmp
  169.   = get-c-function("strcmp", args: list(<c-string>, <c-string>),
  170.            result: <integer>);
  171. define constant strlen
  172.   = get-c-function("strlen", args: list(<c-string>), result: <integer>);
  173.  
  174. define method class-for-copy(string :: <c-string>)
  175.   <byte-string>;
  176. end method class-for-copy;
  177.  
  178. define method make(cls == <c-string>, #key size: sz = 0, fill = ' ')
  179.   let result = as(<c-string>, malloc(sz + 1));
  180.   let fill-byte = as(<integer>, fill);
  181.   for (i from 0 below sz)
  182.     unsigned-byte-at(result, offset: i) := fill-byte;
  183.   end for;
  184.   unsigned-byte-at(result, offset: sz) := 0;
  185.   result;
  186. end method make;
  187.  
  188. define method forward-iteration-protocol(str :: <c-string>)
  189.   values(0, #f,
  190.      method (str, state) state + 1 end method,
  191.      method (str, state, limit)
  192.        unsigned-byte-at(str, offset: state) == 0;
  193.      end method,
  194.      method (str, state) state end method,
  195.      method (str, state)
  196.        as(<character>, unsigned-byte-at(str, offset: state));
  197.      end method,
  198.      method (value :: <character>, str, state)
  199.        unsigned-byte-at(str, offset: state) := as(<integer>, value);
  200.      end method,
  201.      method (str, state) state end method);
  202. end method forward-iteration-protocol;
  203.  
  204. define method \<
  205.     (str1 :: <c-string>, str2 :: <c-string>)
  206.  => result :: <object>;
  207.   strcmp(str1, str2) < 0;
  208. end method \<;
  209.  
  210. define method size (string :: <c-string>)
  211.  => result :: <integer>;
  212.   strlen(string);
  213. end method size;
  214.  
  215. define method export-value (cls == <integer>, value :: <boolean>)
  216.  => (result :: <integer>);
  217.   if (value) 1 else 0 end if;
  218. end method export-value;
  219.  
  220. define method import-value (cls == <boolean>, value :: <integer>)
  221.  => (result :: <boolean>);
  222.   value ~= 0;
  223. end method import-value;
  224.  
  225. // Normal statically typed pointers can be regarded as vectors of length 1.
  226. // However, C sometimes allows you to access more than the first element, so
  227. // we do no bounds checking.
  228. //
  229. define method element
  230.     (vec :: <statically-typed-pointer>, index :: <integer>, #key default)
  231.  => (result :: <object>);
  232.   pointer-value(vec, index: index);
  233. end method element;
  234.  
  235. // For "normal" ponters, the size is wired in as "1".  However, subtypes can
  236. // redefine this to higher values and the iteration protocol will still work.
  237. //
  238. define method size
  239.     (vec :: <statically-typed-pointer>) => (result :: <integer>);
  240.   1;
  241. end method size;
  242.  
  243. // Straightforward vector FIP.  We duplicate it here to avoid problems with
  244. // possible recursive definitions of element.
  245. //
  246. define method forward-iteration-protocol (vec :: <statically-typed-pointer>);
  247.   values(0, vec.size,
  248.      method (c, s) s + 1 end,    // next-state
  249.      method (c, s, l) s >= l end, // finished-state?
  250.      method (c, s) s end,    // current-key
  251.      method (c, s) pointer-value(c, index: s) end, // current-element
  252.      method (v, c, s) pointer-value(c, index: s) := v end, // ""-setter
  253.      method (c, s) s end); // copy-state
  254. end method forward-iteration-protocol;
  255.